package com.commerce.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.commerce.common.constant.RabbitMQConstant;
import com.commerce.common.entity.FlashSale;
import com.commerce.common.entity.FlashSaleProduct;
import com.commerce.common.message.FlashSaleMessage;
import com.commerce.product.constant.RedisConstant;
import com.commerce.product.mapper.FlashSaleMapper;
import com.commerce.product.mapper.FlashSaleProductMapper;
import com.commerce.product.service.FlashSaleService;
import com.commerce.product.service.FlashSaleStockService;
import com.commerce.product.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;

@Slf4j
@Service
public class FlashSaleServiceImpl extends ServiceImpl<FlashSaleMapper, FlashSale> implements FlashSaleService {

    @Autowired
    private FlashSaleProductMapper flashSaleProductMapper;

    @Autowired
    private FlashSaleStockService flashSaleStockService;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    public FlashSale getCurrentFlashSale() {
        LocalDateTime now = LocalDateTime.now();

        // 查询当前时间正在进行的秒杀活动
        LambdaQueryWrapper<FlashSale> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.le(FlashSale::getStartTime, now)
                .gt(FlashSale::getEndTime, now)
                .eq(FlashSale::getStatus, 1)
                .orderByDesc(FlashSale::getCreateTime)
                .last("LIMIT 1");

        return getOne(queryWrapper);
    }

    @Override
    public List<FlashSale> getAllPeriods() {
        // 获取今天的所有时间段
        LocalDateTime startOfDay = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
        LocalDateTime endOfDay = startOfDay.plusDays(1);
        
        LambdaQueryWrapper<FlashSale> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ge(FlashSale::getStartTime, startOfDay)
                .lt(FlashSale::getEndTime, endOfDay)
                .orderByAsc(FlashSale::getStartTime);
        
        return list(queryWrapper);
    }

    @Override
    public List<FlashSaleProduct> getFlashSaleProducts(Long flashSaleId) {
        LambdaQueryWrapper<FlashSaleProduct> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(FlashSaleProduct::getFlashSaleId, flashSaleId)
                .eq(FlashSaleProduct::getStatus, 1)
                .orderByAsc(FlashSaleProduct::getId);
        
        return flashSaleProductMapper.selectList(queryWrapper);
    }

    @Override
    public boolean purchaseFlashSaleProduct(Long flashSaleId, Long productId, Long userId, Integer quantity) {
        return purchaseFlashSaleProductWithUserInfo(flashSaleId, productId, userId, quantity, null, null);
    }

    /**
     * 秒杀购买（带用户信息）
     */
    public boolean purchaseFlashSaleProductWithUserInfo(Long flashSaleId, Long productId, Long userId,
                                                       Integer quantity, String userIp, String userAgent) {
        try {
            log.info("开始处理秒杀请求: flashSaleId={}, productId={}, userId={}, quantity={}",
                    flashSaleId, productId, userId, quantity);

            // 1. 基础参数校验
            if (flashSaleId == null || productId == null || userId == null || quantity == null || quantity <= 0) {
                log.warn("秒杀参数无效");
                return false;
            }

            // 2. 检查秒杀活动是否有效
            FlashSale flashSale = getById(flashSaleId);
            if (flashSale == null || flashSale.getStatus() != 1) {
                log.warn("秒杀活动无效: flashSaleId={}", flashSaleId);
                return false;
            }

            LocalDateTime now = LocalDateTime.now();
            if (now.isBefore(flashSale.getStartTime()) || now.isAfter(flashSale.getEndTime())) {
                log.warn("秒杀活动未开始或已结束: flashSaleId={}", flashSaleId);
                return false;
            }

            // 3. 获取秒杀商品信息
            FlashSaleProduct flashSaleProduct = getFlashSaleProductFromCache(flashSaleId, productId);
            if (flashSaleProduct == null) {
                log.warn("秒杀商品不存在: flashSaleId={}, productId={}", flashSaleId, productId);
                return false;
            }

            // 4. 检查用户购买限制
            if (!checkUserPurchaseLimit(userId, flashSaleId, productId, quantity, flashSaleProduct.getLimitPerUser())) {
                log.warn("用户购买超过限制: userId={}, flashSaleId={}, productId={}", userId, flashSaleId, productId);
                return false;
            }

            // 5. 使用分布式锁防止重复购买
            String lockKey = RedisConstant.buildFlashSaleLockKey(flashSaleId, productId, userId);
            String lockValue = UUID.randomUUID().toString();

            if (!redisUtil.tryLock(lockKey, lockValue, RedisConstant.LOCK_EXPIRE_TIME)) {
                log.warn("获取分布式锁失败，可能重复提交: userId={}", userId);
                return false;
            }

            try {
                // 6. Redis库存预减
                if (!flashSaleStockService.deductStock(flashSaleId, productId, quantity)) {
                    log.warn("库存预减失败: flashSaleId={}, productId={}, quantity={}", flashSaleId, productId, quantity);
                    return false;
                }

                // 7. 记录用户购买限制
                recordUserPurchase(userId, flashSaleId, productId, quantity);

                // 8. 发送异步消息处理订单
                FlashSaleMessage message = new FlashSaleMessage(
                    userId, flashSaleId, productId,
                    flashSaleProduct.getProductName(),
                    flashSaleProduct.getMainImage(),
                    flashSaleProduct.getFlashPrice(),
                    quantity, userIp, userAgent
                );

                rabbitTemplate.convertAndSend(
                    RabbitMQConstant.FLASH_SALE_EXCHANGE,
                    RabbitMQConstant.FLASH_SALE_ORDER_ROUTING_KEY,
                    message
                );

                log.info("秒杀请求处理成功，已发送异步消息: userId={}, messageId={}", userId, message.getMessageId());
                return true;

            } finally {
                // 释放分布式锁
                redisUtil.releaseLock(lockKey, lockValue);
            }

        } catch (Exception e) {
            log.error("秒杀购买处理失败: flashSaleId={}, productId={}, userId={}, error={}",
                     flashSaleId, productId, userId, e.getMessage(), e);

            // 发生异常时回滚库存
            try {
                flashSaleStockService.rollbackStock(flashSaleId, productId, quantity);
            } catch (Exception rollbackException) {
                log.error("库存回滚失败: {}", rollbackException.getMessage());
            }

            return false;
        }
    }

    @Override
    public boolean addFlashSale(FlashSale flashSale) {
        flashSale.setCreateTime(LocalDateTime.now());
        flashSale.setUpdateTime(LocalDateTime.now());
        return save(flashSale);
    }

    @Override
    public boolean addFlashSaleProduct(Long flashSaleId, FlashSaleProduct product) {
        product.setFlashSaleId(flashSaleId);
        product.setCreateTime(LocalDateTime.now());
        product.setUpdateTime(LocalDateTime.now());
        return flashSaleProductMapper.insert(product) > 0;
    }

    @Override
    public boolean updateFlashSaleProduct(Long id, Long flashSaleId, Integer status, java.util.Map<String, Object> params) {
        try {
            // 查询现有的秒杀商品
            FlashSaleProduct product = flashSaleProductMapper.selectById(id);
            if (product == null) {
                return false;
            }

            // 更新基本信息
            product.setStatus(status);
            product.setUpdateTime(LocalDateTime.now());

            // 如果有其他参数，也进行更新
            if (params.containsKey("productName")) {
                product.setProductName(params.get("productName").toString());
            }
            if (params.containsKey("mainImage")) {
                product.setMainImage(params.get("mainImage").toString());
            }
            if (params.containsKey("originalPrice")) {
                product.setOriginalPrice(new java.math.BigDecimal(params.get("originalPrice").toString()));
            }
            if (params.containsKey("flashPrice")) {
                product.setFlashPrice(new java.math.BigDecimal(params.get("flashPrice").toString()));
            }
            if (params.containsKey("discountPercent")) {
                product.setDiscountPercent(new java.math.BigDecimal(params.get("discountPercent").toString()));
            }
            if (params.containsKey("stock")) {
                product.setStock(Integer.parseInt(params.get("stock").toString()));
            }
            if (params.containsKey("limitPerUser")) {
                product.setLimitPerUser(Integer.parseInt(params.get("limitPerUser").toString()));
            }

            return flashSaleProductMapper.updateById(product) > 0;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public boolean deleteFlashSaleProduct(Long id) {
        return flashSaleProductMapper.deleteById(id) > 0;
    }

    @Override
    public boolean updateFlashSale(FlashSale flashSale) {
        flashSale.setUpdateTime(LocalDateTime.now());
        return updateById(flashSale);
    }

    @Override
    public boolean deleteFlashSale(Long id) {
        return removeById(id);
    }

    /**
     * 从缓存获取秒杀商品信息
     */
    private FlashSaleProduct getFlashSaleProductFromCache(Long flashSaleId, Long productId) {
        try {
            String productKey = RedisConstant.buildFlashSaleProductKey(flashSaleId, productId);
            Object cachedProduct = redisUtil.get(productKey);

            if (cachedProduct != null) {
                return (FlashSaleProduct) cachedProduct;
            }

            // 缓存中没有，从数据库查询
            LambdaQueryWrapper<FlashSaleProduct> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(FlashSaleProduct::getFlashSaleId, flashSaleId)
                   .eq(FlashSaleProduct::getProductId, productId)
                   .eq(FlashSaleProduct::getStatus, 1);

            FlashSaleProduct product = flashSaleProductMapper.selectOne(wrapper);

            // 缓存到Redis
            if (product != null) {
                redisUtil.set(productKey, product, RedisConstant.FLASH_SALE_EXPIRE_TIME);
            }

            return product;

        } catch (Exception e) {
            log.error("获取秒杀商品缓存失败: flashSaleId={}, productId={}, error={}",
                     flashSaleId, productId, e.getMessage());
            return null;
        }
    }

    /**
     * 检查用户购买限制
     */
    private boolean checkUserPurchaseLimit(Long userId, Long flashSaleId, Long productId,
                                         Integer quantity, Integer limitPerUser) {
        try {
            if (limitPerUser == null || limitPerUser <= 0) {
                return true; // 没有限制
            }

            String limitKey = RedisConstant.buildUserFlashSaleLimitKey(userId, flashSaleId, productId);
            Integer purchased = redisUtil.getStock(limitKey);

            if (purchased == null) {
                purchased = 0;
            }

            return (purchased + quantity) <= limitPerUser;

        } catch (Exception e) {
            log.error("检查用户购买限制失败: userId={}, flashSaleId={}, productId={}, error={}",
                     userId, flashSaleId, productId, e.getMessage());
            return true; // 异常时允许购买
        }
    }

    /**
     * 记录用户购买数量
     */
    private void recordUserPurchase(Long userId, Long flashSaleId, Long productId, Integer quantity) {
        try {
            String limitKey = RedisConstant.buildUserFlashSaleLimitKey(userId, flashSaleId, productId);
            redisUtil.increment(limitKey, quantity, RedisConstant.FLASH_SALE_EXPIRE_TIME);
        } catch (Exception e) {
            log.error("记录用户购买数量失败: userId={}, flashSaleId={}, productId={}, quantity={}, error={}",
                     userId, flashSaleId, productId, quantity, e.getMessage());
        }
    }

    @Override
    public List<FlashSaleProduct> getHotFlashSaleProducts(Integer limit) {
        try {
            // 获取热门秒杀商品（按销量排序）
            LambdaQueryWrapper<FlashSaleProduct> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(FlashSaleProduct::getStatus, 1)
                   .orderByDesc(FlashSaleProduct::getSoldCount)
                   .last("LIMIT " + limit);
            return flashSaleProductMapper.selectList(wrapper);
        } catch (Exception e) {
            log.error("获取热门秒杀商品失败", e);
            return new java.util.ArrayList<>();
        }
    }

    @Override
    public List<FlashSale> getUpcomingFlashSales(Integer limit) {
        try {
            // 获取即将开始的秒杀活动
            LocalDateTime now = LocalDateTime.now();
            LambdaQueryWrapper<FlashSale> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(FlashSale::getStatus, 1)
                   .gt(FlashSale::getStartTime, now)
                   .orderByAsc(FlashSale::getStartTime)
                   .last("LIMIT " + limit);
            return getBaseMapper().selectList(wrapper);
        } catch (Exception e) {
            log.error("获取即将开始的秒杀活动失败", e);
            return new java.util.ArrayList<>();
        }
    }

    @Override
    public List<FlashSaleProduct> searchFlashSaleProducts(String keyword, Integer page, Integer size) {
        try {
            // 搜索秒杀商品
            LambdaQueryWrapper<FlashSaleProduct> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(FlashSaleProduct::getStatus, 1);

            if (keyword != null && !keyword.trim().isEmpty()) {
                wrapper.and(w -> w.like(FlashSaleProduct::getProductName, keyword));
            }

            wrapper.orderByDesc(FlashSaleProduct::getCreateTime);

            // 分页
            int offset = (page - 1) * size;
            wrapper.last("LIMIT " + offset + ", " + size);

            return flashSaleProductMapper.selectList(wrapper);
        } catch (Exception e) {
            log.error("搜索秒杀商品失败", e);
            return new java.util.ArrayList<>();
        }
    }
}